#!/usr/bin/env python
################################################################################
#            __  __            _   ____        _ _ ____        _              #
#           |  \/  | ___  __ _| |_| __ )  __ _| | | __ )  ___ | |_           #
#           | |\/| |/ _ \/ _` | __|  _ \ / _` | | |  _ \ / _ \| __|         #
#           | |  | |  __/ (_| | |_| |_) | (_| | | | |_) | (_) | |_          #
#           |_|  |_|\___|\__,_|\__|____/ \__,_|_|_|____/ \___/ \__|          #
#                                                                             #
#                                     by                                       #
# _______ .______       _______  _______   ______   ______   _______   _______  #
#|   ____||   _  \     |   ____||   ____| /      | /  __  \ |       \ |   ____|  #
#|  |__   |  |_)  |    |  |__   |  |__   |  ,----'|  |  |  ||  .--.  ||  |__      #
#|   __|  |      /     |   __|  |   __|  |  |     |  |  |  ||  |  |  ||   __|      #
#|  |     |  |\  \----.|  |____ |  |____ |  `----.|  `--'  ||  '--'  ||  |____      #
#|__|     | _| `._____||_______||_______| \______| \______/ |_______/ |_______|    #
#                                                                                 #
#                                Identify Core                                   #
#                             Circuits FrameWork                                #
#
# Coders
#
#	Justin Giorgi (rebel_kid)
#
# Debuggers
#
#	Justin Giorgi (rebel_kid)
#	Lachlan Gilmour (chilli0)
#	David Liedle (spiderbyte)
#	(Polarina)
#	(prologic)
#
################################################################################
#                                                                              #
#                               GPL Licensed                                   #
#                                                                              #
################################################################################

# Imports
from toolkit import find
from hashlib import sha512
from circuits.core import listener, Event, Component

# Sets plugin variables
__id__ = "identification"
__core__ = True

# Creates event classes
class IRCmessage(Event): pass
class IdentifiedAdd(Event): pass
class IdentifiedDel(Event): pass

class Identify(Component):

	def __init__(self, *args, **kwargs):
		# Important: Call the super constructors to initialize the Component.
		super(Network, self).__init__(*args, **kwargs)
		self.channel = kwargs["channel"]
		self.usalt = find("meatballbot", "usalt")
		self.psalt = find("meatballbot", "psalt")
		self.identified = {}
	
	# Finds the user and pass of an identify command and passes to the login function	
	@listener("privcmd-identify")
	def identify(self, **kwargs):
		if len(kwargs["command"]) > 1:
			# If two arguments are supplied the user is specified in command
			if len(kwargs["command"]) > 2:
				user = kwargs["command"][1]
				passwd = kwargs["command"][2]
				self.login(user, passwd, **kwargs)
				
			# If one argument is supplied the user is specified as the nick
			else:		
				user = kwargs["source"]
				passwd = kwargs["command"][1]
				self.login(user, passwd, **kwargs)
				
		# If no arguements were supplied an error message is issued
		else:
			self.push(IRCmessage(kwargs["source"], "I need more information."), "issue-message", self.channel)
	
	# Logs a user in			
	def login(self, user, passwd, **kwargs):
		# Hashes the user and pass and calls from the database
		huser = sha512("%s%s" % (self.usalt, user)).hexdigest()
		hpasswd = sha512("%s%s" % (self.psalt, passwd)).hexdigest()
		kwargs["cursor"].execute("SELECT id FROM users WHERE user = %s AND password = %s AND active = 1", (huser, hpasswd))
		data = kwargs["cursor"].fetchone()
		
		# Sends bad user or pass
		if data is None:
			self.push(IRCmessage(kwargs["source"], "Incorrect username or password."), "issue-message", self.channel)
		
		# Logs in
		else:
			self.identified[(kwargs["ident"], kwargs["host"])] = data[0]
			self.push(IdentifiedAdd((kwargs["ident"], kwargs["host"]), data[0]), "identified-add", self.channel)
			self.push(IRCmessage(kwargs["source"], "Login successful.", self.channel)
			
	# Forces a user out on request
	@listener("privcmd-forcelogout")
	def forcelogoutcmd(self, **kwargs):
		if len(kwargs["command"]) > 1:
			# If two arguments are supplied the user is specified in command with the password
			if len(kwargs["command"]) > 2:
				user = kwargs["command"][1]
				passwd = kwargs["command"][2]
				self.forcelogout(user, passwd, **kwargs)
				
			# If one argument is supplied the user is specified as the nick with the password
			else:		
				user = kwargs["source"]
				passwd = kwargs["command"][1]
				self.forcelogout(user, passwd, **kwargs)
				
		# If no arguements were supplied 
		else:
			self.push(IRCmessage(kwargs["source"], "I need more information."), "issue-message", self.channel)
	
	# Forcelogout function		
	def forcelogout(self, user, passwd, **kwargs):
		# Hashes the user and pass and calls from the database
		huser = sha512("%s%s" % (self.usalt, user)).hexdigest()
		hpasswd = sha512("%s%s" % (self.psalt, passwd)).hexdigest()
		kwargs["cursor"].execute("SELECT id FROM users WHERE user = %s AND password = %s AND active = 1", (huser, hpasswd))
		data = kwargs["cursor"].fetchone()
		
		# Sends bad user or pass
		if data is None:
			self.push(IRCmessage(kwargs["source"], "Incorrect username or password."), "issue-message", self.channel)
		
		# Logs out and sends success
		else:
			for item in self.identified.items():
				if data[0] == item[1]:
					del self.identified[item[0]]
					self.push(IdentifiedDel(item[0]), "identified-del", self.channel)
			self.push(IRCmessage(kwargs["source"], "Logout successful."), "issue-message", self.channel)
			
	# Logs a user out on request
	@listener("privcmd-logout")
	def logoutcmd(self, **kwargs):
		self.logout(**kwargs)
		
	# Logs a user out on quit
	@listener("relay-quit")
	def onQUIT(self, source, message):
		host = source.split("@")[1]
		ident = source.split("!")[1].split("@")[0]
		source = None
		self.logout(host = host, ident = ident, source = source)
	
	# Logout function
	def logout(self, **kwargs):
		# Checks if the ident and host is in the identified dict and logs out (sends success if source is not none)
		if (kwargs["ident"], kwargs["host"]) in self.identified:
			del self.identified[(kwargs["ident"], kwargs["host"])]
			self.push(IdentifiedDel((kwargs["ident"], kwargs["host"])), "identified-del", self.channel)
			if source is not None:
				self.push(IRCmessage(kwargs["source"], "Logout successful."), "issue-message", self.channel)
				
		# Sends not logged in with ident and host
		else:
			if source is not None:
				self.push(IRCmessage(kwargs["source"], "You are not logged in with your current ident and host. Please use forcelogout."), "issue-message", self.channel)
		
def startup(channel, cursor):
	plugin = Identify(channel = channel, cursor = cursor)
	return (__id__, plugin)

def kill():
	return __id__
